<%
'######################################################################
'## App.TagLib.asp
'## -------------------------------------------------------------------
'## Feature     :   AppCore TagLib
'## Version     :   v1.0.0
'## Author      :   Lajox (lajox@19www.com)
'## Update Date :   2014/12/01 22:10
'## HomePage	:   http://www.19www.com
'## -------------------------------------------------------------------
'## Description :   AppCore 系统标签解析
'######################################################################

Class Cls_App_TagCom

	Private s_dictName, s_tbPrefix
	Private b_debug
	Private o_db, o_ds
	Public o_dict, o_pager

	Private Sub Class_Initialize()
		On Error Resume Next
		b_debug = App.Debug
		Set o_dict = AB.C.Dict()
		Set o_pager = AB.C.Dict()
		s_tbPrefix = App.Dao.tbPrefix '数据表前缀
		Set o_db = App.Dao.db() '数据库驱动托管于App.Dao.db
		AB.Use "E" : AB.E.Use "Md5"
		AB.Use "Fso"
		AB.Use "A"
		On Error GoTo 0
	End Sub

	Private Sub Class_Terminate()
		Set o_dict = Nothing
		Set o_pager = Nothing
	End Sub
	
	Public Function Parse(ByVal str)
		On Error Resume Next
		If Err Then Err.Clear
		'解析标签块(如带sql参数标签)
		Dim Matches, Match, Matches2, Match2, tag, var, condi, inner, f, ext, rpStr, extra, cvar, cval, sql, table, where
		Dim hasData, hasConn, hasPageSize, s_has, s_size, md5, tmp, i, FromX, FromY, offset, rows
		Dim st1, st2, st3, st4, st5, st6
		md5 = LCase(AB.E.Md5.To8(Now()& AB.C.Rand(10000,99999)))
		Set Matches = AB.C.RegMatch(str, "(\{\$?([a-zA-Z0-9_\x7f-\xff]+)\s+(.+?)\s*\})([\s\S]*?)(\{\/\$?\2\s*\})")
		For Each Match In Matches
			var = Trim(Match.SubMatches(1))
			condi = Match.SubMatches(2)
			inner = Match.SubMatches(3)
			o_dict.RemoveAll
			hasPageSize = False
			sql = ""
			Set Matches2 = AB.C.RegMatch(condi, "([a-zA-Z0-9_]+)\s*=\s*(['""]?)([^'""\s]*|[^\2]*?)\2")
			For Each Match2 In Matches2
				cvar = Trim(Match2.SubMatches(0))
				cval = Match2.SubMatches(2)
				cval = AB.C.RP( cval, Array("\\","\@","\#","\$"), Array(Chr(17),Chr(18),Chr(19),Chr(20)) )
				cval = AB.C.RegReplace( cval, "\(\$([\w]+)\)", """& $1 &""" ) '替换变量
				cval = AB.C.RegReplace( cval, "<"&"%=(.+)%"&">", """& $1 &""" ) '替换变量
				Select Case LCase(cvar)
					Case "sql"
						sql = Trim(cval)
						o_dict("sql") = Trim(sql)
						'Set App.View.RsData(md5) = o_db.GRS(sql) '只读
						'Set App.View.RsData(md5) = o_db.Exec(sql) '可读写
						'str = AB.C.RP( str, Match.Value, "<"&"% Set "&var&" = App.View.RsData("""&md5&""") : Do While Not "&var&".Eof %"&">" &_
						'"" & inner &"<"&"% "&var&".MoveNext : Loop %"&">" )
					Case "pagesize" '设置分页数
						hasPageSize = True
						o_dict("pagesize") = Trim(cval)
						If AB.C.IsNum(Trim(cval)) Then
							o_pager("size") = CLng(Trim(cval))
							If o_pager("size")<=0 Then o_pager("size") = CLng(App.View.PageSize)
						Else
							o_pager("size") = CLng(App.View.PageSize)
						End If
						o_pager("sql") = Trim(sql) '记录分页sql语句
					Case "pagemark" '分页标识
						hasPageSize = True
						o_pager("mark") = Trim(cval)
						If Trim(o_pager("mark"))="" Then o_pager("mark") = App.View.PageMark
					Case Else
						o_dict(LCase(cvar)) = cval
				End Select
			Next
			
			offset = CLng(o_dict("offset")) '偏移量
			rows = CLng(o_dict("rows")) '取数量
			If offset<0 Then offset = 0
			If rows<0 Then rows = 0
			If hasPageSize Then '有设置分页
				o_pager("set") = var '传递分页设置
				o_pager("mark") = AB.C.IfHas(Trim(o_pager("mark")), "p") '分页标识符
				o_pager("size") = AB.C.IfHas(CLng(o_pager("size")), CLng(App.View.PageSize)) '每页数量
				o_pager("no") = CLng(App.Req( o_pager("mark") )) '当前页码
				If o_pager("no")<=0 Then o_pager("no") = 1
				o_pager("offset") = offset '偏移量
				o_pager("rows") = rows '取数量
			End If
			hasData = False
			If Trim(o_dict("data"))<>"" Then '直接传递data参数
				o_dict("data") = Trim(o_dict("data"))
				o_dict("data") = AB.C.RegReplace( o_dict("data"), "(['""])([^\1]*?)\1", """$2""" )
				hasData = True
			End If
			hasConn = False
			If Trim(o_dict("conn"))<>"" Then '带conn参数
				o_dict("conn") = AB.C.RegReplace( o_dict("conn"), "(['""])([^\1]*?)\1", """$2""" )
				o_dict("conn") = Trim(o_dict("conn"))
				hasConn = True
			End If
			If Trim(sql)<>"" Or Trim(o_dict("table"))<>"" Or Trim(o_dict("data"))<>"" Then '带sql参数 或 table参数 或 data参数
				If Trim(sql)="" And Trim(o_dict("table"))<>"" Then
					sql = "SELECT "& AB.C.IIF(Trim(o_dict("field"))="","*",Trim(o_dict("field"))) &" FROM " & ( AB.C.IIF(o_dict.Exists("prefix"), o_dict("prefix"), s_tbPrefix) & Trim(o_dict("table")) ) &_
						" WHERE 1=1 " & AB.C.IIF(Trim(o_dict("where"))="",""," AND " & o_dict("where")) &_
						"" & AB.C.IIF(Trim(o_dict("order"))="",""," ORDER BY " & o_dict("order"))
				End If
				sql = AB.C.RP(sql, "#@", AB.C.IIF(o_dict.Exists("prefix"), o_dict("prefix"), s_tbPrefix)) '替换数据表前缀
				sql = AB.C.RP(sql, Array(Chr(17),Chr(18),Chr(19),Chr(20)), Array("\","@","#","$"))
				If hasPageSize Then '有设置分页
					If o_pager("no")<=0 Then o_pager("no") = 1
					md5 = LCase(AB.E.Md5.To8(Now()& AB.C.Rand(10000,99999)))
					If False Then '屏蔽
						str = AB.C.RP( str, Match.Value, "<"&"% Dim PageCount_"&md5&", PageNo_"&md5&", i_"&md5&", PosX_"&md5&", PosY_"&md5&" "& VBCrlf &" " &_
								" AB.C.Dim(""conn_"& md5 &""") "& VBCrlf &" " &_
								AB.C.IIF(hasConn, " If AB.C.IsConn("& o_dict("conn") &") Then Set conn_"&md5&" = "& o_dict("conn") &" Else Set conn_"&md5&" = App.Dao.db.Conn ", "Set conn_"&md5&" = App.Dao.db.Conn ") & VBCrlf &" " &_
								AB.C.IIF(hasData, " If AB.C.IsRs("& o_dict("data") &") Then Set "&var&" = "& o_dict("data") &" ", " Set "&var&" = AB.C.NewRs() : "&var&".Open """&sql&""",conn_"&md5&",1,3 ") & VBCrlf &" " &_
								" If AB.C.IsRs("&var&") And Not AB.C.IsNul("&var&") Then "& VBCrlf &" " &_
								" Set "&var&" = App.Dao.LimitRs("&var&", """&offset&""", """&rows&""") "& VBCrlf &" " &_
								" "&var&".PageSize = "& o_pager("size") &" "& VBCrlf &" " &_
								" PageCount_"&md5&" = "&var&".PageCount "& VBCrlf &" " &_
								" PageNo_"&md5&" = "& o_pager("no") &" "& VBCrlf &" " &_
								" If PageNo_"&md5&" > PageCount_"&md5&" Then PageNo_"&md5&" = PageCount_"&md5&" "& VBCrlf &" " &_
								" If Not "&var&".Eof Then "& VBCrlf &" " &_
								" "&var&".AbsolutePage = PageNo_"&md5&" "& VBCrlf &" " &_
								" For i_"&md5&"=0 to "& o_pager("size") &"-1 "& VBCrlf &" " &_
								" If "&var&".Bof Or "&var&".Eof Then Exit For "& VBCrlf &" " &_
								" 'If i_"&md5&"=0 Then : PosX_"&md5&" = "&var&".AbsolutePosition : End If "& VBCrlf &" " &_
								" 'PosY_"&md5&" = "&var&".AbsolutePosition "& VBCrlf &" " &_
								" %"&">" &_
								"" & inner & "" &_
								"<"&"% "&var&".MoveNext "& VBCrlf &" Next "& VBCrlf &" End If "& VBCrlf &" " &_
								" 'App.View.RsData(""posx"") = PosX_"&md5&" "& VBCrlf &" " &_
								" 'App.View.RsData(""posy"") = PosY_"&md5&" "& VBCrlf &" " &_
								" End If " &_
								" %"&">" )
					Else
						str = AB.C.RP( str, Match.Value, "<"&"% Dim i_"&md5&", PageCount_"&md5&" "& VBCrlf &" " &_
								" AB.C.Dim(""conn_"& md5 &""") "& VBCrlf &" " &_
								AB.C.IIF(hasConn, " If AB.C.IsConn("& o_dict("conn") &") Then Set conn_"&md5&" = "& o_dict("conn") &" Else Set conn_"&md5&" = App.Dao.db.Conn ", "Set conn_"&md5&" = App.Dao.db.Conn ") & VBCrlf &" " &_
								AB.C.IIF(hasData, " If AB.C.IsRs("& o_dict("data") &") Then Set "&var&" = "& o_dict("data") &" ", " Set "&var&" = AB.C.NewRs() : "&var&".Open """&sql&""",conn_"&md5&",1,3 ") & VBCrlf &" " &_
								" If AB.C.IsRs("&var&") And Not AB.C.IsNul("&var&") Then "& VBCrlf &" " &_
								" Set "&var&" = App.Dao.LimitRs("&var&", """&offset&""", """&rows&""") "& VBCrlf &" " &_
								" If Not ("&var&".Bof And "&var&".Eof) Then "& VBCrlf &" " &_
								" 	"&var&".AbsolutePosition = "&var&".AbsolutePosition + ((Abs("& o_pager("no") &")-1) * "& o_pager("size") &") "& VBCrlf &" " &_
								" 	If "&var&".Eof Then "& VBCrlf &" " &_
								" 		PageCount_"&md5&" = Abs(Int(-("&var&".RecordCount / "& o_pager("size") &"))) "& VBCrlf &" " &_
								" 		"&var&".AbsolutePosition = (PageCount_"&md5&"-1) * "& o_pager("size") &" + 1 "& VBCrlf &" " &_
								" 	End If "& VBCrlf &" " &_
								" 	For i_"&md5&"=0 to ("& o_pager("size") &"-1) "& VBCrlf &" " &_
								" 	If "&var&".Eof Then Exit For "& VBCrlf &" " &_
								" %"&">" &_
								"" & inner & "" &_
								"<"&"% "&var&".MoveNext "& VBCrlf &" 	Next "& VBCrlf &" End If "& VBCrlf &" End If "& VBCrlf &" " &_
								" %"&">" )
					End If
				Else '无分页
					str = AB.C.RP( str, Match.Value, "<"&"% "& VBCrlf &" " &_
					" AB.C.Dim(""conn_"& md5 &""") "& VBCrlf &" " &_
					AB.C.IIF(hasConn, " If AB.C.IsConn("& o_dict("conn") &") Then Set conn_"&md5&" = "& o_dict("conn") &" Else Set conn_"&md5&" = App.Dao.db.Conn ", "Set conn_"&md5&" = App.Dao.db.Conn ") & VBCrlf &" " &_
					AB.C.IIF(hasData, " If AB.C.IsRs("& o_dict("data") &") Then Set "&var&" = "& o_dict("data") &" ", " Set "&var&" = AB.C.NewRs() : "&var&".Open """&sql&""",conn_"&md5&",1,3 ") & VBCrlf &" " &_
					" If AB.C.IsRs("&var&") And Not AB.C.IsNul("&var&") Then "& VBCrlf &" " &_
					" Set "&var&" = App.Dao.LimitRs("&var&", """&offset&""", """&rows&""") "& VBCrlf &" " &_
					" Do While Not "&var&".Eof %"&">" &_
					"" & inner &"<"&"% "&var&".MoveNext "& VBCrlf &" Loop "& VBCrlf &" End If %"&">" )
				End If
			Else
				o_pager("no") = CLng(App.Req( o_pager("mark") )) '当前页码
				If o_pager("no")<=0 Then o_pager("no") = 1
				If hasPageSize Then '有设置分页
					o_pager("set") = var '传递分页设置
					o_pager("mark") = AB.C.IfHas(Trim(o_pager("mark")), "p") '分页标识符
					o_pager("size") = AB.C.IfHas(o_pager("size"), CLng(App.View.PageSize)) '每页数量
					s_size = o_pager("size")
				Else
					s_size = 0
				End If
				md5 = LCase(AB.E.Md5.To8(Now()& AB.C.Rand(10000,99999)))
				If AB.A.InArray( LCase(o_dict("type")), Array("array","arr","dict","dictionary","rs","recordset") ) Then
					offset = CLng(o_dict("offset")) '偏移量
					rows = CLng(o_dict("rows")) '取数量
					If offset<0 Then offset = 0
					If rows<0 Then rows = 0
					o_dict("key") = Trim(o_dict("key")) '索引key
					If o_dict("key")="" Then o_dict("key") = "i"
				End If
				'数组循环标签解析，需设置参数 type='arr' . 可选参数：begin='数字' key='i'
				If LCase(o_dict("type")) = "array" Or LCase(o_dict("type")) = "arr" Then
					str = AB.C.RP( str, Match.Value, "<"&"% Dim arr_"&md5&" "& VBCrlf &" " &_
					" arr_"&md5&" = App.View.arrEach("""& var &""", """& o_pager("no") &""", """& s_size &""", """& offset &""", """& rows &""" ) " &_
					" "& VBCrlf &" If Not AB.C.isNul("& var &") Then "& VBCrlf &" For "& o_dict("key") &" = arr_"&md5&"(0) To arr_"&md5&"(1) %"&">" &_
					"" & inner &"<"&"% Next "& VBCrlf &" End If %"&">" )
				'字典循环标签解析，需设置参数 type='dict' . 可选参数：begin='数字' key='i'
				ElseIf LCase(o_dict("type")) = "dict" Or LCase(o_dict("type")) = "dictionary" Then
					str = AB.C.RP( str, Match.Value, "<"&"% Dim arr_"&md5&", k_"&md5&" "& VBCrlf &" " &_
					" arr_"&md5&" = App.View.arrEach("""& var &""", """& o_pager("no") &""", """& s_size &""", """& offset &""", """& rows &""" ) " &_
					" "& VBCrlf &" k_"&md5&" = 0 "& VBCrlf &" " &_
					" If Not AB.C.isNul("& var &") Then "& VBCrlf &" For Each "& o_dict("key") &" In "& var &" "& VBCrlf &" " &_
					" If k_"&md5&" >= arr_"&md5&"(0) and k_"&md5&" <= arr_"&md5&"(1) Then %"&">" &_
					" " & inner &"<"&"% End If "& VBCrlf &" k_"&md5&" = k_"&md5&" + 1 "& VBCrlf &" Next "& VBCrlf &" End If %"&">" )
				'Rs记录集循环标签解析，需设置参数 type='rs'
				ElseIf LCase(o_dict("type")) = "rs" Or LCase(o_dict("type")) = "recordset" Then
					If s_size<=0 Then '无设置分页
						str = AB.C.RP( str, Match.Value, "<"&"% Dim arr_"&md5&" "& VBCrlf &" " &_
						AB.C.IIF(hasData, " If AB.C.IsRs("& o_dict("data") &") Then Set "&var&" = "& o_dict("data") &" ", " ") & VBCrlf &" " &_
						" If AB.C.IsRs("&var&") And Not AB.C.IsNul("&var&") Then "& VBCrlf &" " &_
						" Set "&var&" = App.Dao.LimitRs("&var&", """&offset&""", """&rows&""") "& VBCrlf &" " &_
						" Do While Not "&var&".Eof " &_
						" %"&">" & inner &_
						"<"&"% "&var&".MoveNext "& VBCrlf &" Loop "& VBCrlf &" End If %"&">" )
					Else
						str = AB.C.RP( str, Match.Value, "<"&"%  " &_
						" Dim arr_"&md5&", k_"&md5&", t_"&md5&" "& VBCrlf &" " &_
						" k_"&md5&" = 0 "& VBCrlf &" " &_
						AB.C.IIF(hasData, " If AB.C.IsRs("& o_dict("data") &") Then Set "&var&" = "& o_dict("data") &" ", " ") & VBCrlf &" " &_
						" If AB.C.IsRs("&var&") And Not AB.C.IsNul("&var&") Then "& VBCrlf &" " &_
						" Set "&var&" = App.Dao.LimitRs("&var&", """&offset&""", """&rows&""") "& VBCrlf &" " &_
						" "&var&".PageSize = "& s_size &" "& VBCrlf &" " &_
						" "&var&".Move(" & (o_pager("no")-1) * s_size &") "& VBCrlf &" " &_
						" t_"&md5&" = AB.C.IIF("&o_pager("no")&">"&var&".PageCount,"&var&".PageCount,"&o_pager("no")&")"& VBCrlf &" " &_
						" If "&var&".RecordCount>0 And "&var&".Eof Then "& VBCrlf &" "&var&".AbsolutePosition = (t_"&md5&"-1)*"&var&".PageSize+1 "& VBCrlf &" End If "& VBCrlf &" " &_
						" Do While Not "&var&".Eof "& VBCrlf &" " &_
						" k_"&md5&" = k_"&md5&" + 1 " &_
						" %"&">" & inner &_
						"<"&"% If k_"&md5&" > "& (s_size-1) &" Then "& VBCrlf &" Exit Do "& VBCrlf &" End If "& VBCrlf &" " &_
						" "&var&".MoveNext "& VBCrlf &" Loop "& VBCrlf &" End If %"&">" )
					End If
				End If
			End If
			If AB.C.RegTest(str, "({\$?([a-zA-Z0-9_\x7f-\xff]+)\s+(.+?)\s*})([\s\S]*?)(\{\/\$?\2\s*\})") Then
				str = Me.Parse(str) '递归解析同类标签
			End If
		Next
		Set Matches = Nothing
		Set Matches2 = Nothing
		str = AB.C.RegReplace( str, "\{\$?([a-zA-Z0-9_\x7f-\xff]+)[\(\[][""']?(\d+)[""']?[\)\]](\s*[\+\-]\s*\w+)?\s*\}", "<"&"%=$1($2) $3%"&">" )
		str = AB.C.RegReplace( str, "\{\$?([a-zA-Z0-9_\x7f-\xff]+)[\(\[][""']?(\d+)[""']?[\)\]](\+\+\s*)\}", "<"&"% $1(""$2"") = $1($2) + 1 %"&">" )
		str = AB.C.RegReplace( str, "\{\$?([a-zA-Z0-9_\x7f-\xff]+)[\(\[][""']?(\d+)[""']?[\)\]](\-\-\s*)\}", "<"&"% $1(""$2"") = $1($2) - 1 %"&">" )

		str = AB.C.RegReplace( str, "\{\$?([a-zA-Z0-9_\x7f-\xff]+)[\(\[][""']([a-zA-Z0-9_\x7f-\xff]+)[""'][\)\]]\s*\}", "<"&"%=$1(""$2"")%"&">" )
		str = AB.C.RegReplace( str, "\{\$?([a-zA-Z0-9_\x7f-\xff]+)\([""']([a-zA-Z0-9_\x7f-\xff]+)[""'][\)\]](\+\+\s*)\}", "<"&"% $1(""$2"") = $1(""$2"") + 1 %"&">" )
		str = AB.C.RegReplace( str, "\{\$?([a-zA-Z0-9_\x7f-\xff]+)\([""']([a-zA-Z0-9_\x7f-\xff]+)[""'][\)\]](\-\-\s*)\}", "<"&"% $1(""$2"") = $1(""$2"") - 1 %"&">" )

		str = AB.C.RegReplace( str, "\{\$?([a-zA-Z0-9_\x7f-\xff]+)[\(\[](\s*\d+\s*)[\)\]](\s*[\+\-]\s*\w+)?\s*\}", "<"&"%=$1($2) $3 %"&">" )
		str = AB.C.RegReplace( str, "\{\$?([a-zA-Z0-9_\x7f-\xff]+)[\[](\$?[a-zA-Z0-9_\x7f-\xff]+)[\]](\s*[\+\-]\s*\w+)?\s*\}", "<"&"%=$1(""$2"") $3 %"&">" )
		str = AB.C.RegReplace( str, "\{\$?([a-zA-Z0-9_\x7f-\xff]+)[\(](\$?[a-zA-Z0-9_\x7f-\xff]+)[\)](\s*[\+\-]\s*\w+)?\s*\}", "<"&"%=$1($2) $3 %"&">" )
		str = AB.C.RegReplace( str, "\{\$?([a-zA-Z0-9_\x7f-\xff]+)[\(\[](\$?[a-zA-Z0-9_\x7f-\xff]+)[\)\]](\+\+\s*)\}", "<"&"% $1($2) = $1($2) + 1 %"&">" )
		str = AB.C.RegReplace( str, "\{\$?([a-zA-Z0-9_\x7f-\xff]+)[\(\[](\$?[a-zA-Z0-9_\x7f-\xff]+)[\)\]](\-\-\s*)\}", "<"&"% $1($2) = $1($2) - 1 %"&">" )
		Set Matches = AB.C.RegMatch(str, "\{\$?(([a-zA-Z0-9_\x7f-\xff]+)([\(\[]([a-zA-Z0-9_\x7f-\xff\'\""]+)[\)\]])+)\}")
		For Each Match In Matches
			tmp = Match.SubMatches(0)
			tmp = AB.C.RegReplace( tmp, "(['""])([^\1]*?)\1", """$2""" )
			str = AB.C.RP( str, Match.Value, "<"&"%="& tmp &"%"&">" )
		Next
		Set Matches = Nothing
		'' 下面代码太多，改用函数调用法
		' str = AB.C.RegReplace( str, "\{\$?([a-zA-Z0-9_\x7f-\xff]+)\.([a-zA-Z0-9_\x7f-\xff]+)(\s*[\+\-]\s*\d+)?\}", _
				' "<"&"% If IsObject($1) And (TypeName($1)=""Recordset"" Or TypeName($1)=""Dictionary"" Or TypeName($1)=""Cls_AB_List"") Then "& VBCrlf &" " &_
				' "AB.C.Echo $1(""$2"") $3 "& VBCrlf &" ElseIf IsObject($1) Then "& VBCrlf &" AB.C.Echo $1.$2 $3 "& VBCrlf &" " &_
				' "Else "& VBCrlf &" AB.C.Echo """" "& VBCrlf &" End If %"&">" )
		' str = AB.C.RegReplace( str, "\{\$?([a-zA-Z0-9_\x7f-\xff]+)\.([a-zA-Z0-9_\x7f-\xff]+)(\+\+\s*)\}", _
				' "<"&"% If IsObject($1) And (TypeName($1)=""Recordset"" Or TypeName($1)=""Dictionary"" Or TypeName($1)=""Cls_AB_List"") Then "& VBCrlf &" " &_
				' "$1(""$2"") = $1(""$2"") + 1 "& VBCrlf &" ElseIf IsObject($1) Then "& VBCrlf &" $1.$2 = $1.$2 + 1 "& VBCrlf &" " &_
				' "Else "& VBCrlf &" AB.C.Echo """" "& VBCrlf &" End If %"&">" )
		' str = AB.C.RegReplace( str, "\{\$?([a-zA-Z0-9_\x7f-\xff]+)\.([a-zA-Z0-9_\x7f-\xff]+)(\-\-\s*)\}", _
				' "<"&"% If IsObject($1) And (TypeName($1)=""Recordset"" Or TypeName($1)=""Dictionary"" Or TypeName($1)=""Cls_AB_List"") Then "& VBCrlf &" " &_
				' "$1(""$2"") = $1(""$2"") - 1 "& VBCrlf &" ElseIf IsObject($1) Then "& VBCrlf &" $1.$2 = $1.$2 - 1 "& VBCrlf &" " &_
				' "Else "& VBCrlf &" AB.C.Echo """" "& VBCrlf &" End If %"&">" )
		'' 改用函数调用法
		' str = AB.C.RegReplace( str, "\{\$?([a-zA-Z0-9_\x7f-\xff]+)\.([a-zA-Z0-9_\x7f-\xff]+)(\s*[\+\-]\s*\d+)?\}", _
				' "<"&"%=App.View.ObjAttr(""$1"",""$2"",""$3"")%"&">" )
		' str = AB.C.RegReplace( str, "\{\$?([a-zA-Z0-9_\x7f-\xff]+)\.([a-zA-Z0-9_\x7f-\xff]+)(\+\+\s*)\}", _
				' "<"&"%=App.View.ObjAttr(""$1"",""$2"",""+1"")%"&">" )
		' str = AB.C.RegReplace( str, "\{\$?([a-zA-Z0-9_\x7f-\xff]+)\.([a-zA-Z0-9_\x7f-\xff]+)(\-\-\s*)\}", _
				' "<"&"%=App.View.ObjAttr(""$1"",""$2"",""-1"")%"&">" )
		str = AB.C.RegReplace( str, "\{\$?([a-zA-Z0-9_\x7f-\xff]+)\.([a-zA-Z0-9_\x7f-\xff]+(\.[\w\x7f-\xff]+)*)(\s*[\+\-]\s*\d+)?\}", _
				"<"&"%=App.View.ObjAttr(""$1"",""$2"",""$4"")%"&">" )
		str = AB.C.RegReplace( str, "\{\$?([a-zA-Z0-9_\x7f-\xff]+)\.([a-zA-Z0-9_\x7f-\xff]+(\.[\w\x7f-\xff]+)*)(\+\+\s*)\}", _
				"<"&"%=App.View.ObjAttr(""$1"",""$2"",""+1"")%"&">" )
		str = AB.C.RegReplace( str, "\{\$?([a-zA-Z0-9_\x7f-\xff]+)\.([a-zA-Z0-9_\x7f-\xff]+(\.[\w\x7f-\xff]+)*)(\-\-\s*)\}", _
				"<"&"%=App.View.ObjAttr(""$1"",""$2"",""-1"")%"&">" )
		'拓展变量,带函数:
		Set Matches = AB.C.RegMatch(str, "\{\$?([a-zA-Z0-9_\x7f-\xff]+)((\.[\w\x7f-\xff]+)*)\s*[\|]\s*(\w+)\s*(\=\s*(.+?))?\s*\}")
		For Each Match In Matches
			st1 = Trim(Match.SubMatches(0))
			st2 = Trim(Match.SubMatches(1))
			If st2<>"" Then st2 = AB.C.CRight(st2,".")
			st3 = Trim(Match.SubMatches(3)) '函数名
			st4 = Trim(Match.SubMatches(4))
			st5 = Trim(Match.SubMatches(5)) '参数
			If st4<>"" Then
				st6 = "App.View.ObjAttr("""&st1&""","""&st2&""","""")"
				st5 = AB.C.RP(st5,"###",st6)
				str = AB.C.RP( str, Match.Value, "<"&"%="& st3 &"("& st5 &")%"&">")
			Else
				st6 = "App.View.ObjAttr("""&st1&""","""&st2&""","""")"
				str = AB.C.RP( str, Match.Value, "<"&"%="& st3 &"("& st6 &")%"&">")
			End If
		Next
		Set Matches = Nothing
		'-清除未处理的包含标签
		str = AB.C.RegReplace( str, "\{\/\$?[a-zA-Z0-9_]+\}", "<"&"% %"&">" )
		str = AB.C.RegReplace( str, "\{\$?([a-zA-Z0-9_\x7f-\xff]+)\s+([.+)\s*\}", "<"&"% %"&">" )
		'解析{@var}指令语句
		Set Matches = AB.C.RegMatch(str, "\{@([a-zA-Z0-9_\x7f-\xff]+)\s+(.+?)\s*\}")
		For Each Match In Matches
			o_dict.RemoveAll
			var = Trim(Match.SubMatches(0))
			condi = Match.SubMatches(1)
			tmp = "" : sql = "" : table="" : where=""
			Set Matches2 = AB.C.RegMatch(condi, "([a-zA-Z0-9_]+)\s*=\s*(['""]?)([^'""\s]*|[^\2]*?)\2")
			For Each Match2 In Matches2
				cvar = Trim(Match2.SubMatches(0))
				cval = Match2.SubMatches(2)
				Select Case LCase(cvar)
					Case "sql", "table", "where"
						tmp = Trim(cval)
						tmp = AB.C.RP( tmp, "\\", Chr(24) ) '替换普通\符号
						tmp = AB.C.RP( tmp, "\$", Chr(25) ) '替换普通$符号
						tmp = AB.C.RegReplace( tmp, "\(\$([\w]+)\)", """& $1 &""" ) '替换变量
						tmp = AB.C.RP( tmp, Chr(25), "$" ) '替换普通$符号
						tmp = AB.C.RP( tmp, Chr(24), "\" ) '替换普通\符号
						If LCase(cvar)="sql" Then
							o_dict("sql") = Trim(tmp)
						ElseIf LCase(cvar)="table" Then
							o_dict("table") = Trim(tmp)
						ElseIf LCase(cvar)="where" Then
							If Trim(tmp)<>"" Then tmp = " WHERE " & Trim(tmp)
							o_dict("where") = tmp
						End If
					Case Else 'e.g. data
						o_dict(LCase(cvar)) = cval
				End Select
			Next
			If o_dict.Exists("sql") Then
				tmp = o_dict("sql")
				tmp = AB.C.RP(tmp, Array("\@","\#"), Array(Chr(18),Chr(19)))
				tmp = AB.C.RP(tmp, "#@", AB.C.IIF(o_dict.Exists("prefix"), o_dict("prefix"), s_tbPrefix) ) '替换数据表前缀
				tmp = AB.C.RP(tmp, Array(Chr(18),Chr(19)), Array("@","#"))
				o_dict("sql") = Trim(tmp)
			End If
			If LCase(var)="count" Then '解析{@count sql=''} 或 {@count table='' where=''}指令语句
				If Trim(o_dict("data"))<>"" Then
					str = AB.C.RP( str, Match.Value, "<"&"% tmp_"&md5&" = App.View.ObjCount("""& o_dict("data") &""") : AB.C.Echo tmp_"&md5&" %"&">" )
				ElseIf Trim(o_dict("sql"))<>"" Then
					str = AB.C.RP( str, Match.Value, "<"&"% Set RsCount_"&md5&" = App.Dao.db.Exec("""& o_dict("sql") &""") : AB.C.Echo RsCount_"&md5&".RecordCount %"&">" )
				ElseIf Trim(o_dict("table"))<>"" Then
					sql = "SELECT * FROM " & AB.C.IIF(o_dict.Exists("prefix"), o_dict("prefix"), s_tbPrefix) & o_dict("table") & o_dict("where")
					str = AB.C.RP( str, Match.Value, "<"&"% Set RsCount_"&md5&" = App.Dao.db.Exec("""&sql&""") : AB.C.Echo RsCount_"&md5&".RecordCount %"&">" )
				Else
					str = AB.C.RP( str, Match.Value, "<"&"%=0%"&">" )
				End If
			ElseIf LCase(var)="pager" Then '解析{@pager data='' sql='' size='10' mark='p'}指令语句
				tmp = ""
				If Trim(o_dict("count"))<>"" Then
					tmp = CLng(o_dict("count"))
				ElseIf o_dict("data")<>"" Then
					tmp = o_dict("data")
				ElseIf o_dict("sql")<>"" Then
					tmp = Trim(o_dict("sql"))
				Else
					'If hasPageSize And o_pager("set")<>"" Then tmp = o_pager("set")
					If o_pager("set")<>"" Then tmp = o_pager("set")
				End If
				If Trim(o_dict("mark"))<>"" Then o_pager("mark") = o_dict("mark")
				If Trim(o_dict("size"))<>"" Then o_pager("size") = o_dict("size")
				If Trim(o_dict("offset"))<>"" Then o_pager("offset") = o_dict("offset") '偏移量
				If Trim(o_dict("rows"))<>"" Then o_pager("rows") = o_dict("rows") '取数量
				o_pager("mark") = AB.C.IfHas(Trim(o_pager("mark")), "p") '分页标识符
				o_pager("size") = AB.C.IfHas(o_pager("size"), CLng(App.View.PageSize)) '每页数量
				o_pager("no") = CLng(App.Req( o_pager("mark") )) '当前页码
				If o_pager("no")<=0 Then o_pager("no") = 1
				str = AB.C.RP( str, Match.Value, "<"&"% Set "&var&" = App.View.TagCom.PageData( """& tmp &""", """& o_pager("no") &""", """& o_pager("size") &""", """& o_pager("mark") &""", """& o_pager("offset") &""", """& o_pager("rows") &""" )  %"&">" )
			ElseIf LCase(var)="load" Or LCase(var)="css" Or LCase(var)="js" Then '解析{@load href="../jq.js"} 载入css或js文件标签
				o_dict("href") = Trim(o_dict("href"))
				f = o_dict("href")
				ext = LCase(AB.Fso.ExtOf(f))
				If ext<>".js" And ext<>".css" Then
					If LCase(var)="css" Then ext = ".css"
					If LCase(var)="js" Then ext = ".js"
				End If
				If ext<>".js" And ext<>".css" Then ext = ".js" '其他
				If Left(f,1)="/" Then
					f = Trim(f)
				ElseIf Left(f,1)="." Then
					If Left(f,3)="../" Then
						f = UpDir(App.View.Path_Js) & "/" & AB.C.CRight(f,"../")
					ElseIf Left(f,2)="./" Then
						If ext = ".js" Then
							f = App.View.Path_Js & "/" & AB.C.CRight(f,"./")
						ElseIf ext = ".css" Then
							f = App.View.Path_Css & "/" & AB.C.CRight(f,"./")
						End If
					End If
				Else
					If ext = ".js" Then
						f = App.View.Path_Js & "/" & f
					ElseIf ext = ".css" Then
						f = App.View.Path_Css & "/" & f
					End If
				End If
				If ext = ".js" Then
					str = AB.C.RP( str, Match.Value, "<script src="""& f &""" type=""text/javascript""></script>" )
				ElseIf ext = ".css" Then
					str = AB.C.RP( str, Match.Value, "<link href="""& f &""" rel=""stylesheet"" type=""text/css"" />" )
				End If
			End If
		Next
		Set Matches = Nothing
		Set Matches2 = Nothing
		'解析{@empty for='var'}..{/@empty} 和 {@noempty for='var'}..{/@noempty}指令语句
		Set Matches = AB.C.RegMatch(str, "\{@(empty|noempty)\s+(.+?)\s*\}([\s\S]*?)\{\/@\1\}")
		For Each Match In Matches
			inner = Match.SubMatches(2)
			condi = Match.SubMatches(1)
			tag = Match.SubMatches(0)
			var = ""
			Set Matches2 = AB.C.RegMatch(condi, "([a-zA-Z0-9_]+)\s*=\s*(['""]?)([^'""\s]*|[^\2]*?)\2")
			For Each Match2 In Matches2
				cvar = Trim(Match2.SubMatches(0))
				cval = Match2.SubMatches(2)
				cval = AB.C.RegReplace( cval, "(['""])([^\1]*?)\1", """$2""" )
				Select Case LCase(cvar)
					Case "for"
						var = Trim(cval)
				End Select
			Next
			If InStr(inner,"{@else}") Then inner = AB.C.RP( inner, "{@else}", "<"&"% Else %"&">" )
			If InStr(inner,"{else}") Then inner = AB.C.RP( inner, "{else}", "<"&"% Else %"&">" )
			If var="" Then
				rpStr = ""
			Else
				If tag="empty" Then
					rpStr = "<"&"% If AB.C.IsNul("&var&") Then %"&">"& inner &"<"&"% End If %"&">"
				Else
					rpStr = "<"&"% If Not AB.C.IsNul("&var&") Then %"&">"& inner &"<"&"% End If %"&">"
				End If
			End If
			str = AB.C.RP( str, Match.Value, rpStr )
		Next
		Set Matches = Nothing
		Set Matches2 = Nothing
		str = AB.C.RegReplace( str, "\{@([a-zA-Z0-9_\x7f-\xff]+)\s+(.+?)\s*\}", "" )
		str = AB.C.RegReplace( str, "\{\/@[a-zA-Z0-9_]+\}", "" )
		'解析函数标签 例{:func()}
		Set Matches = AB.C.RegMatch(str, "\{\:\s*(.+?)\s*(\+\+|\-\-)?\s*\}")
		For Each Match In Matches
			var = Trim(Match.SubMatches(0))
			condi = Match.SubMatches(1)
			var = AB.C.RegReplace( var, "\$([a-zA-Z][\w]*)", "$1" )
			var = AB.C.RegReplace( var, "(['""])([^\1]*?)\1", """$2""" )
			If Trim(condi)="" Then
				rpStr = "<"&"%="&var&"%"&">"
			Else
				If Trim(condi)="++" Then condi = "+1"
				If Trim(condi)="--" Then condi = "-1"
				rpStr = "<"&"% "&var&""& extra &" = "&var&""& extra &"" & condi & " %"&">"
			End If
			str = AB.C.RP( str, Match.Value, rpStr )
		Next
		Set Matches = Nothing
		Parse = str
		On Error GoTo 0
	End Function

	Public Function PageData(ByVal d, ByVal PageNo, ByVal PageSize, ByVal PageMark, ByVal offset, ByVal rows)
		On Error Resume Next
		Dim sql, ObjTmp, Total, PageCount : d = Trim(d)
		Dim min, max, a, temp, RsCxTmp, start, over
		If Trim(PageMark)="" Then PageMark = App.View.PageMark '分页标识符
		If CLng(PageSize)<=0 Then PageSize = CLng(App.View.PageSize) '每页数量
		If CLng(PageNo)<=0 Then PageNo = 1 '分页码
		If CLng(offset)<=0 Then offset = 0 '偏移量
		If CLng(rows)<=0 Then rows = 0 '取数量
		' o_pager.RemoveAll '先清空对象
		' o_pager("offset") = 0
		' o_pager("rows") = 0
		o_pager("mark") = PageMark
		o_pager("size") = PageSize
		'_分页插件设置
		App.View.Pager.Url = ""
		App.View.Pager.Param = PageMark
		App.View.Pager.PageSize = PageSize
		If AB.C.IsNum(d) Then '数字
			Total = CLng(d)
		ElseIf AB.C.RegTest(d, "^[a-zA-Z]\w*$") Then '传递变量
			If IsObject(Eval(d)) Then Set ObjTmp = Eval(d) Else ObjTmp = Eval(d)
			If AB.C.IsNul(ObjTmp) Then
				Total = 0
			Else
				If AB.C.IsDict(ObjTmp) Or IsArray(ObjTmp) Then
					If AB.C.IsDict(ObjTmp) Then
						Total = ObjTmp.Count
					Else
						Total = AB.A.Len(ObjTmp)
					End If
					If Total>0 And (offset<>0 Or rows<>0) Then '重新计算总记录数
						start = offset
						over = Total - 1
						If rows>0 Then over = offset+rows-1
						If over>Total-1 Or over=0 Then over = Total - 1
						Total = over - start + 1
					End If
				ElseIf IsObject(ObjTmp) And TypeName(ObjTmp)="Recordset" Then
					'Total = ObjTmp.RecordCount
					Total = App.Dao.RsCount(ObjTmp)
					'App.View.Pager.Dom = ObjTmp 'Pager.Dom传值对象rs记录集
				ElseIf AB.C.isInt(ObjTmp) Then
					Total = CLng(ObjTmp)
				Else
					Total = 0
					If CLng(ObjTmp)>0 Then Total = CLng(ObjTmp)
				End If
			End If
		Else '传递sql语句
			sql = Trim(d)
			sql = AB.C.RP(sql, "@", s_tbPrefix) '替换数据表前缀
			sql = AB.C.RP( sql, "\$", Chr(25) ) '替换普通$符号
			sql = AB.C.RegReplace( sql, "\(\$([\w]+)\)", """& $1 &""" ) '替换变量
			sql = AB.C.RP( sql, Chr(25), "\$" ) '替换普通$符号
			Set RsCxTmp = App.Dao.db.Exec(sql)
			'Total = RsCxTmp.RecordCount
			Total = App.Dao.RsCount(RsCxTmp)
			Set RsCxTmp = Nothing
		End If
		App.View.Pager.Total = Total '设置Pager.Total总记录数
		o_pager("total") = Total '总记录数
		If Total<=0 Then
			PageCount = 1
		Else
			If (Total Mod PageSize) = 0 Then
				PageCount = CLng(Total \ PageSize)
			Else
				PageCount = CLng(Total \ PageSize) + 1
			End If
		End If
		o_pager("count") = PageCount '总页数
		If AB.C.RegTest(d, "^[a-zA-Z0-9_]+$") and TypeName(ObjTmp)="Recordset" and App.View.RsData("posx")>0 Then 'Rs变量
			min = App.View.RsData("posx")
			max = App.View.RsData("posy")
		Else
			If (PageNo * PageSize) <= Total Then
				min = (PageNo - 1) * PageSize + 1
				max = PageNo * PageSize
			Else
				min = (PageCount - 1) * PageSize + 1
				max = Total
			End If
		End If
		If min<0 Then min=0
		If max<0 Then max=0
		o_pager("no") = PageNo '页码
		o_pager("begin") = AB.C.IIF(Total<=0,0,min) '开始标识
		o_pager("end") = max '开始标识
		o_pager("first") = 1
		o_pager("prev") = AB.C.IIF(PageNo<=1, 1, AB.C.IIF(PageCount<=1,1,PageNo-1))
		o_pager("next") = AB.C.IIF(PageNo-PageCount>=0, PageCount, PageNo+1)
		o_pager("last") = PageCount
		o_pager("first_s") = App.View.Pager.First
		o_pager("prev_s") = App.View.Pager.Prev
		o_pager("next_s") = App.View.Pager.Next
		o_pager("last_s") = App.View.Pager.Last
		o_pager("bar") = App.View.Pager.Html
		Set PageData = o_pager
		On Error GoTo 0
	End Function

	Private Function UpDir(ByVal p)
		p = AB.C.RP(p,"\","/")
		p = AB.C.IIF(Right(p,1)="/", Left(p, Len(p)-1), p)
		If Instr(p,"/")>0 Then
			p = Left(p, InstrRev(p,"/")-1)
		Else
			p = ""
		End If
		UpDir = p
	End Function
	
End Class
%>